/*
    BibleNotebook - A bible reader software
    Copyright (C) 2014  Williams Fernando Lopez

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
 */

package com.simplebible.dictionary;

import com.simplebible.dictionary.objects.SimpleIndex;
import com.simplebible.dictionary.objects.DictDefinition;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.crosswire.common.xml.XMLUtil;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookData;
import org.crosswire.jsword.book.sword.BookType;
import org.crosswire.jsword.book.sword.ConfigEntryType;
import org.crosswire.jsword.book.sword.SwordBookMetaData;
import org.crosswire.jsword.passage.Key;
import wl.util.Utils;
import com.simplebible.objects.Preferences;

/**
 *
 * @author Williams Lopez
 */
public class SwordDictionary implements IDictionary{

    private SwordBookMetaData swordBookMetaData;
    private Book swordBook;

    private String id;
    private String name;
    private String url;
    private String copyright;
    private String description;
    private String idioma;
    private int size;
    private List<String> words;
    private List<Key> keyList;
    private File path;
    private HashMap<String, List<String>> simpleIndex;


    public SwordDictionary(File path) throws Exception{

        swordBookMetaData = new SwordBookMetaData(path, "booksword", path.getParentFile().getParentFile().toURI());

        name = swordBookMetaData.getProperty(ConfigEntryType.DESCRIPTION)!=null?swordBookMetaData.getProperty(ConfigEntryType.DESCRIPTION).toString():null;
        url  = swordBookMetaData.getProperty(ConfigEntryType.COPYRIGHT_CONTACT_ADDRESS)!=null? swordBookMetaData.getProperty(ConfigEntryType.COPYRIGHT_CONTACT_ADDRESS).toString():null;
        copyright= swordBookMetaData.getProperty(ConfigEntryType.COPYRIGHT)!=null?swordBookMetaData.getProperty(ConfigEntryType.COPYRIGHT).toString():null;
        description = swordBookMetaData.getProperty(ConfigEntryType.ABOUT)!=null ? swordBookMetaData.getProperty(ConfigEntryType.ABOUT).toString():null;
        id = swordBookMetaData.getInitials();
        if(swordBookMetaData.getLanguage()!=null){
            idioma = swordBookMetaData.getLanguage().getCode();
        }else{
            idioma = Preferences.IDIOMA_EN;
        }
        this.path = path;

        if(id==null){
            id=path.getName();
        }

        BookType modtype = swordBookMetaData.getBookType();
        if (modtype == null || modtype.getBookCategory() == null){
            throw new Exception("Error");
        }
        swordBook = modtype.createBook(swordBookMetaData);
        Key keys = swordBook.getGlobalKeyList();
        size = keys.getCardinality();

        simpleIndex = new HashMap<String, List<String>>();
        words = new ArrayList<String>();
        keyList = new ArrayList<Key>();
        Iterator it = keys.iterator();
        while(it.hasNext()){
            Key k = (Key)it.next();
            String word = k.getName().toUpperCase();
            words.add(word);
            keyList.add(k);

            String indexKey = Utils.substring(word, 0, 3);
            List<String> idx = simpleIndex.get(indexKey);
            if(idx == null ){
                idx = new ArrayList<String>();
                simpleIndex.put(indexKey, idx);
            }
            idx.add(word);
        }
    }


    public void close() throws IOException {
        swordBook.deactivate(null);
    }

    public DictDefinition get(String word) throws Exception {
        int index = words.indexOf(word.toUpperCase());
        if(index >= 0){
            Key k = keyList.get(index);
            BookData bdata = new BookData(swordBook, k);
            DictDefinition def = new DictDefinition();
            def.setWord(word);
            def.setDefinitions(new String[]{ XMLUtil.writeToString(bdata.getSAXEventProvider()).trim() });
            return def;
        }
        return null;
    }

    public void put(DictDefinition def) throws Exception {
        throw new UnsupportedOperationException("Not supported");
    }

    public boolean remove(String word) throws Exception {
        throw new UnsupportedOperationException("Not supported");
    }

    public void setDictionaryInfo(String name, String url, String copiryght, String description,String lang) throws IOException {
        throw new UnsupportedOperationException("Not supported");
    }

    public String getDictionaryId() {
        return id;
    }

    public String getDictionaryCopyright() {
        return copyright;
    }

    public String getDictionaryDescription() {
        return description;
    }

    public String getDictionaryName() {
        return name;
    }

    public String getDictionaryUrl() {
        return url;
    }

    public int size() {
        return size;
    }

    public List<String> listSimilarWords(String word) throws Exception {
        word = word.toUpperCase();
        String indexKey = Utils.substring(word, 0, 3);
        List<String> inIndex = simpleIndex.get(indexKey);
        List<String> similars = new ArrayList<String>();
        if (inIndex != null) {
            for (String w : inIndex) {
                if (Utils.areSimilar(word, w)) {
                    similars.add(w);
                }
            }
        } else {
            if (word.trim().length() > 3) {
                for (String w : getAllWords()) {
                    if (word.startsWith(root)) {
                        if (Utils.areSimilar(word, w)) {
                            similars.add(w);
                        }

                    }
                }
            }
        }
        return similars;
    }

    public List<String> getAllWords() throws IOException {
        return words;
    }

    public boolean removeOfSystem() throws Exception {
        close();
        String name = path.getName().substring(0, path.getName().lastIndexOf("."));
        String modDrv = (String)swordBookMetaData.getProperty(ConfigEntryType.MOD_DRV);
        String dataPath = (String)swordBookMetaData.getProperty(ConfigEntryType.DATA_PATH);
        File installFile = new File(dataPath);

        installFile = installFile.getParentFile();

        path.delete();
        Utils.deleteDirectory(installFile);

        return true;
    }

    @Override
    public String toString() {
        return "[DIC-"+getDictionaryId()+"] "+getDictionaryName();
    }

    public String getIdioma() {
        return idioma;
    }

    public Collection<String> getIndexKeys() throws Exception {
        return simpleIndex.keySet();
    }

    public List<String> getIndexKeyWords(String menuKey) {
        return simpleIndex.get(menuKey);
    }

    public SimpleIndex getIndex() throws Exception {
        return DictionaryUtils.createSimpleIndex(getAllWords());
    }



}
